package api

import (
	"fmt"
	"github.com/golang/protobuf/ptypes/empty"
	"golang.org/x/net/context"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"gsms/internal/conf"
	"gsms/internal/model"
	"gsms/internal/service"
	"gsms/internal/utils"
	"net/http"
)

// Server represents the gRPC server
type Server struct {
	smsService *service.SmsService
}

func (s *Server) DummyHandler(_ context.Context, _ *empty.Empty) (*HealthCheckResp, error) {
	return &HealthCheckResp{Message: "pong"}, nil
}

func (s *Server) SmsCodeSend(ctx context.Context, req *SmsSendReq) (*OperationResult, error) {
	sms := model.SmsVerify{To: req.Phone, From: req.AppId, VerifyType: req.MessageType,
		Status: model.SmsStatusUnused, Code: req.Code}
	smsHis := model.SmsHistory{
		RequestID: req.RequestId,
		To:        req.Phone,
		From:      req.AppId,
		Status:    model.SmsUnSent,
	}
	if err := s.smsService.Send(ctx, sms, smsHis); err != nil {
		return nil, status.Errorf(codes.Unknown, "发送验证码失败, %v", err)
	}
	return &OperationResult{Message: "SUCCESS"}, nil
}

func New(c *conf.Config) (*Server, error) {
	srv, err := service.New(c)
	if err != nil {
		return nil, err
	}
	return &Server{smsService: srv}, nil
}

// CodeVerify generates response to a request
func (s *Server) CodeVerify(ctx context.Context, in *VerifyReq) (*VerifyResp, error) {
	if !utils.VerifyMobileFormat(in.Phone) {
		return nil, status.Errorf(codes.InvalidArgument, "手机号格式非法")
	}
	if !conf.Conf.AllowedServers.IsAllowed(in.AppId) {
		return nil, status.Errorf(codes.InvalidArgument, "appid格式非法, %v", conf.Conf.AllowedServers.Names)
	}

	sms := model.SmsVerify{To: in.Phone, From: in.AppId, VerifyType: in.MessageType, Code: in.Code}
	matched, err := s.smsService.Verify(sms)
	if err != nil {
		return nil, status.Errorf(codes.Internal, "验证码校验失败")
	}
	var result string
	switch matched {
	case false:
		result = "不通过"
	default:
		result = "通过"
	}

	return &VerifyResp{Message: fmt.Sprintf("校验结果: %v", result), Status: http.StatusOK, VerifyResult: matched}, nil
}

func Close(ser *Server, ctx context.Context) {
	ser.smsService.Close(ctx)
}
